import pygame
from PyPixelCore.Setting import Color_type, basic_line_interval, basic_word_interval
from PyPixelCore.block.MultiLineTextBlock import MultiLineTextBlock

"""
    SuperMultiLineTextBlock --> MultiLineTextBlock --> TextBlock --> Block --> BaseBlock
    多行的文字块
    超级优化MultiLineTextBlock, 通过动态的擦除与填写最后一个块达到模拟文字输入的效果,极大程度的优化了时间, 但是在非追加下性能没有提升
    可直接使用或者继承优化
    功能:
        显示文字
        支持碰撞检测
        支持帧函数与计时器函数
        支持自动检测换行绘制
        支持手动换行控制
        支持手动换行自动换行混合控制
        支持脏精灵优化
        支持字间距
        支持行间距
        支持越界优化
        高效率地逐个追加和删除文字(区域绘制)
        不支持透明
"""


class SuperMultiLineTextBlock(MultiLineTextBlock):
    def __init__(self, text_content="未定义文本", limit_w=0, limit_h=0, point_x=0, point_y=0, layer=0, border_width=1, is_alpha=False):
        self.now_char_logical_pos = [border_width, border_width + basic_line_interval]  # 记录当前需要绘制的位置[x, y]
        self.each_char_logical_pos = []  # 记录每个字符的开头位置(左上角),方便逐个字符地重绘
        self.each_cursor_char_logical_pos = []  # 记录每个字符的开头位置(左上角),方便寻找光标需要的点(本不应该存在于此,为了方便)
        self.word_interval = basic_word_interval
        self.char_arr = []
        # self.text_color_map  #后续可以出一个字体颜色图, 达到绘制各种颜色的效果
        super().__init__(text_content, limit_w, limit_h, point_x, point_y, layer, border_width, is_alpha)
        # 由于特性,不在使用text_arr
        self.set_text_content(text_content)

    def _reload_image_first(self):
        self.is_dirty = True
        if self.is_alpha:
            self.image = pygame.Surface(
                (self.limit_w + self.border_width * 2, self.limit_h + self.border_width * 2), pygame.SRCALPHA)
        else:
            self.image = pygame.Surface(
                (self.limit_w + self.border_width * 2, self.limit_h + self.border_width * 2))
        self.each_char_logical_pos.append(self.now_char_logical_pos.copy())
        self.each_cursor_char_logical_pos.append([self.now_char_logical_pos.copy()])
        self.image.fill(self.bk_color)
        self.rect.size = self.image.get_size()
        if self.border_width != 0:
            pygame.draw.rect(self.image, self.border_color,
                             (0,0,self.limit_w+2*self.border_width,self.limit_h+2*self.border_width) , width=self.border_width)
        # 当改变高宽等大量影响的时候,需要将所有文字重新排版绘制
        for _, each_code in enumerate(self.text_content):
            self.blit_a_char(each_code)
        self.reload_image()

    def reorder_text(self):
        # 对整体文本进行重新排序
        if self.is_alpha:
            self.image = pygame.Surface(
                (self.limit_w + self.border_width * 2, self.limit_h + self.border_width * 2), pygame.SRCALPHA)
        else:
            self.image = pygame.Surface(
                (self.limit_w + self.border_width * 2, self.limit_h + self.border_width * 2))
        self.image.fill(self.bk_color)
        self.rect.size = self.image.get_size()
        self.now_char_logical_pos = [self.border_width, self.border_width + basic_line_interval]
        self.each_char_logical_pos = []
        self.each_cursor_char_logical_pos = []
        self.each_char_logical_pos.append(self.now_char_logical_pos.copy())
        self.each_cursor_char_logical_pos.append([self.now_char_logical_pos.copy()])
        if self.border_width != 0:
            pygame.draw.rect(self.image, self.border_color,
                             (0,0,self.limit_w+2*self.border_width,self.limit_h+2*self.border_width) , width=self.border_width)
        # 当改变高宽等具有影响的数据的时候,需要将所有文字重新排版绘制
        temp_arr = self.char_arr.copy()
        self.char_arr = []
        for char in temp_arr:
            self.blit_a_char(char)

    def reload_image(self):
        if not self.is_dirty:
            return
        self.is_dirty = False

        # 渲染测试用定位点
        # for points in self.each_cursor_char_logical_pos:
        #     for point in points:
        #         pygame.draw.circle(self.image,Color_type.RED, point, 2, width=0)
        # for point in self.each_char_logical_pos:
        #     pygame.draw.circle(self.image, Color_type.RED, point, 2, width=0)
        # # 渲染定位点
        # pygame.draw.circle(self.image, Color_type.GREEN, self.now_char_logical_pos, 2, width=0)

    def blit_a_char(self, char):
        # 维护char_array
        self.char_arr.append(char)
        # 核心绘制
        if char == "\n":  # 换行符处理(手动换行)
            # 记录logical_pos后换行
            # 记录占位符,因为占位符也需要被手动修改

            temp_now_char_logical_pos = [self.border_width, self.now_char_logical_pos[1] + self._font_size + self.line_interval]
            self.each_cursor_char_logical_pos.append([self.now_char_logical_pos.copy(), temp_now_char_logical_pos.copy()])
            self.now_char_logical_pos = temp_now_char_logical_pos.copy()
            self.each_char_logical_pos.append(self.now_char_logical_pos.copy())
            return
        # 超出界面处理(自动换行)
        char_length = self.font.size(char)
        if char_length[0] + self.now_char_logical_pos[0] > self.limit_w:
            temp_now_char_logical_pos = [self.border_width + self.word_interval, self.now_char_logical_pos[1] + self._font_size + self.line_interval]
            self.each_cursor_char_logical_pos.pop()
            self.each_cursor_char_logical_pos.append([self.now_char_logical_pos.copy(), temp_now_char_logical_pos])
            self.now_char_logical_pos =  temp_now_char_logical_pos.copy()


        self.now_char_logical_pos[0] += self.word_interval
        char_surf = self.font.render(char, True, self.font_color, self.bk_color)
        self.image.blit(char_surf,self.now_char_logical_pos)
        self.now_char_logical_pos[0] += char_length[0]
        self.each_char_logical_pos.append(self.now_char_logical_pos.copy())
        self.each_cursor_char_logical_pos.append([self.now_char_logical_pos.copy()])
        self.is_dirty = True

    def blit_text_at_index(self, text, index):
        # 在某个点进行追加性的绘制
        # 获取指针输入后部分的值
        text_next = self.char_arr[index:]

        # 方法1:  先执行删除后面的等量数据,后添加插入数据,最后添加原本在后面的数据(现成函数调用,操作简单,计算复杂)
        # 删除后方等量数据
        self.now_char_logical_pos = self.each_char_logical_pos[-1].copy()
        for _ in range(len(self.char_arr) - index):
            self.delete_char_at_end()
        # 添加待插入数据
        for _, each_char in enumerate(text):
            self.blit_a_char(each_char)
        # 补充原本在后面的数据
        for _, each_char in enumerate(text_next):
            self.blit_a_char(each_char)
        # 恢复指针的位置
        self.now_char_logical_pos = self.each_char_logical_pos[index+len(text)].copy()

        # # 方法2:  找到对应的点位,直接补充插入(性能未验证)

    def delete_char_at_index(self, index):
        # 从指定位置删除元素
        if index == 0:
            return False
        # 方法1:  先执行删除后面的等量数据,后额外删除一个数据,最后添加原本在后面的数据(现成函数调用,操作简单,计算复杂)
        # 获取指针输入后部分的值
        text_next = self.char_arr[index:]
        # 删除后方等量数据
        self.now_char_logical_pos = self.each_char_logical_pos[-1].copy()
        for _ in range(len(self.char_arr) - index):
            self.delete_char_at_end()
        # 额外删除一个数据
        self.delete_char_at_end()
        # 补充原本在后面的数据
        for _, each_char in enumerate(text_next):
            self.blit_a_char(each_char)
        # 恢复指针的位置
        self.now_char_logical_pos = self.each_char_logical_pos[index - 1].copy()

        return True

    def delete_char_at_end(self):
        # 从尾部删除字符
        if len(self.each_char_logical_pos) < 2:
            return False
        # 弹出char_array最后一个字符
        if len(self.char_arr):
            self.char_arr.pop()
        temp_pos = self.each_char_logical_pos[-2]
        temp_pos_after = self.each_char_logical_pos[-1]
        if temp_pos[1] != temp_pos_after[1]:
            # 首部删除
            pygame.draw.rect(self.image, self.bk_color,
                             rect=(
                             self.border_width, temp_pos_after[1], temp_pos_after[0], self._font_size))
        else:
            pygame.draw.rect(self.image, self.bk_color,
                             rect=(temp_pos[0], temp_pos[1], self.now_char_logical_pos[0] - temp_pos[0], self._font_size))
        self.each_char_logical_pos.pop()
        self.each_cursor_char_logical_pos.pop()
        self.is_dirty = True
        if not len(self.each_char_logical_pos):
            self.now_char_logical_pos =  [self.border_width, self.border_width + basic_line_interval]
            return True
        else:
            self.now_char_logical_pos = temp_pos.copy()
            return True

    @property
    def font_size(self):
        return self._font_size

    @property
    def real_height(self):
        return self.each_char_logical_pos[-1][1] + self.font_size

    def set_text_content(self, text_content):
        self.is_dirty = True
        self.char_arr = []
        for _,value in enumerate(text_content):
            self.char_arr.append(value)
        self.reorder_text()

